/**
 * useFrameAnimationController
 *
 * 通用帧动画控制器 Hook
 *
 * 核心职责：
 * - 创建和管理 Animated.Value
 * - 同步创建 interpolations（消除首帧闪动）
 * - 管理动画对象（Animated.CompositeAnimation）
 * - 提供播放控制（play/stop）
 * - 生命周期管理和清理
 *
 * 设计理念：
 * - 同步创建 interpolations，首次渲染即可用
 * - 支持自定义插值创建逻辑，灵活性高
 * - 性能优先：所有对象创建一次，避免重渲染
 * - 类型安全：泛型支持自定义 interpolations 类型
 *
 * @example
 * 基础用法（使用默认 createInterpolations）：
 * ```tsx
 * const frameData = useMemo(() => ({
 *   opacity: [0, 1, 0.5],
 *   scale: [1, 1.2, 1],
 * }), []);
 *
 * const {
 *   animatedValue,
 *   registerAnimation,
 *   interpolations, // ✅ 首次渲染就可用，无需判空
 *   play,
 *   stop,
 *   isPlaying,
 * } = useFrameAnimationController({
 *   frameData,
 *   frameCount: 3,
 *   config: {
 *     onPlayStart: () => console.log('Started'),
 *     onPlayEnd: () => console.log('Ended'),
 *   },
 * });
 * ```
 *
 * @example
 * 自定义插值逻辑：
 * ```tsx
 * const { interpolations } = useFrameAnimationController({
 *   frameData: { opacity: [0, 1, 0] },
 *   frameCount: 3,
 *   createInterpolations: ({ animatedValue, frameData }) => ({
 *     // 自定义缓动函数
 *     opacity: animatedValue.interpolate({
 *       inputRange: [0, 1, 2],
 *       outputRange: frameData.opacity,
 *       easing: Easing.bezier(0.42, 0, 0.58, 1),
 *     }),
 *     // 完全自定义的插值
 *     rotation: animatedValue.interpolate({
 *       inputRange: [0, 2],
 *       outputRange: ['0deg', '360deg'],
 *     }),
 *   }),
 * });
 * ```
 */

import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import { Animated } from 'react-native';

/**
 * Hook 配置接口
 *
 * 包含动画的基础配置和生命周期回调
 */
export interface UseFrameAnimationControllerConfig {
  /** 初始值，默认 0 */
  initialValue?: number;

  /** 插值配置 */
  interpolateConfig?: Animated.InterpolationConfigType;

  /** 播放开始回调 */
  onPlayStart?: () => void;

  /** 播放结束回调（仅在非循环动画自然结束时触发） */
  onPlayEnd?: () => void;

  /** 停止回调 */
  onStop?: () => void;
}

/**
 * Hook 返回值接口
 *
 * @template TFrameData - 帧数据类型
 * @template TInterpolations - interpolations 类型（默认根据 TFrameData 推断）
 */
export interface UseFrameAnimationControllerReturn<
  TFrameData extends Record<string, number[]> = Record<string, number[]>,
  TInterpolations = Record<
    keyof TFrameData,
    Animated.AnimatedInterpolation<number>
  >,
> {
  /** 核心动画值（Hook 创建并管理） */
  animatedValue: Animated.Value;

  /** 注册动画对象 */
  registerAnimation: (animation: Animated.CompositeAnimation) => void;

  /** 获取 interpolations（同步创建，首次渲染即可用）*/
  interpolations: TInterpolations;

  /** 播放动画 */
  play: () => void;

  /** 停止动画并重置到初始值 */
  stop: () => void;

  /** 是否正在播放 */
  isPlaying: boolean;
}

/**
 * 通用帧动画控制器 Hook
 *
 * 核心改进：
 * - interpolations 同步创建，消除首帧闪动问题
 * - 支持自定义插值创建函数，满足复杂场景需求
 * - frameData 和 frameCount 作为必需参数，确保类型安全
 *
 * @template TFrameData - 帧数据类型，必须是 Record<string, number[]>
 * @template TInterpolations - interpolations 返回类型，默认根据 TFrameData 推断
 * @param params - 参数对象
 * @param params.frameData - 帧数据，key 为属性名，value 为各帧的值数组
 * @param params.frameCount - 总帧数
 * @param params.config - 可选配置项（回调函数、初始值等）
 * @param params.createInterpolations - 可选的自定义插值创建函数
 * @returns 控制器对象，包含 interpolations、play/stop 等方法
 */
export function useFrameAnimationController<
  TFrameData extends Record<string, number[]> = Record<string, number[]>,
  TInterpolations = Record<
    keyof TFrameData,
    Animated.AnimatedInterpolation<number>
  >,
>(params: {
  frameData: TFrameData;
  frameCount: number;
  config?: UseFrameAnimationControllerConfig;
  createInterpolations?: (params: {
    animatedValue: Animated.Value;
    frameData: TFrameData;
    frameCount: number;
    config?: Animated.InterpolationConfigType;
  }) => TInterpolations;
}): UseFrameAnimationControllerReturn<TFrameData, TInterpolations> {
  const {
    frameData,
    frameCount,
    config,
    createInterpolations: createInterpolationsFn,
  } = params;
  const {
    initialValue = 0,
    onPlayStart,
    onPlayEnd,
    onStop,
    interpolateConfig,
  } = config ?? {};

  // Hook 内部自动推断
  // const inferredFrameCount =
  //   frameData[Object.keys(frameData)[0]]?.length ?? frameCount;

  // 1. 创建并管理 Animated.Value（只创建一次）
  const animatedValue = useRef(new Animated.Value(initialValue)).current;

  // 2. 同步创建 interpolations（使用 useMemo 确保性能）
  // 优先使用自定义的 createInterpolations，否则使用默认实现
  // ✅ 这里是关键改进：首次渲染就创建 interpolations，消除闪动
  const interpolations = useMemo<TInterpolations>(
    () =>
      createInterpolationsFn?.({
        animatedValue,
        frameData,
        frameCount,
        config: interpolateConfig,
      }) ??
      createInterpolations<TFrameData, TInterpolations>({
        animatedValue,
        frameData,
        frameCount,
        config: interpolateConfig,
      }),
    [
      animatedValue,
      createInterpolationsFn,
      frameCount,
      frameData,
      interpolateConfig,
    ],
  );

  // 3. 管理动画对象
  const animationRef = useRef<Animated.CompositeAnimation | null>(null);

  // 4. 播放状态
  const [isPlaying, setIsPlaying] = useState(false);

  // 5. 注册动画对象
  const registerAnimation = useCallback(
    (animation: Animated.CompositeAnimation) => {
      // 如果有旧动画在播放，先停止
      if (animationRef.current) {
        animationRef.current.stop();
      }
      animationRef.current = animation;
    },
    [],
  );

  // 7. 播放控制
  const play = useCallback(() => {
    if (!animationRef.current) {
      console.warn(
        '[useFrameAnimationController] No animation registered. Call registerAnimation first.',
      );
      return;
    }

    console.log('play');

    onPlayStart?.();

    animationRef.current.start(({ finished }) => {
      if (finished) {
        // 动画自然完成（非 stop 调用）
        setIsPlaying(false);
        onPlayEnd?.();
      }
    });

    setIsPlaying(true);
  }, [onPlayStart, onPlayEnd]);

  const stop = useCallback(() => {
    console.log('stop');
    if (animationRef.current) {
      animationRef.current.stop();
    }
    requestAnimationFrame(() => {
      animationRef.current?.reset(); // ← 停止后重置
      // animatedValue.setValue(initialValue); // !!! 重置到初始值，他可能导致动画值发生抖动 !!!
      setIsPlaying(false);
      onStop?.();
    });
  }, [onStop]);

  // 8. 清理：组件卸载时停止动画
  useEffect(() => {
    return () => {
      console.log('cleanup');
      if (animationRef.current) {
        animationRef.current.stop();
        // animationRef.current.reset(); // !!! 组件已经卸载，不需要重置 !!!
      }
    };
  }, []);

  return {
    animatedValue,
    interpolations,
    play,
    stop,
    isPlaying,
    registerAnimation,
  };
}

/**
 * 工具函数：根据帧数据自动创建 interpolations
 *
 * 这是一个便捷工具函数，自动从帧数据生成标准的线性 interpolations。
 * 适用于大多数常见场景（80%+）。
 *
 * 如果需要复杂的插值逻辑（如自定义缓动、非线性映射等），
 * 请在 useFrameAnimationController 中使用 createInterpolations 参数
 * 传入自定义函数。
 *
 * @example
 * 基础用法：
 * ```tsx
 * const frameData = {
 *   opacity: [0, 1, 0.5],
 *   scale: [1, 1.2, 1],
 * };
 *
 * const interps = createInterpolations({
 *   animatedValue,
 *   frameData,
 *   frameCount: 3,
 * });
 * // interps.opacity, interps.scale 可直接使用
 * ```
 *
 * @example
 * 带配置（extrapolate 等）：
 * ```tsx
 * const interps = createInterpolations({
 *   animatedValue,
 *   frameData: { scale: [1, 1.5, 1] },
 *   frameCount: 3,
 *   config: { extrapolate: 'clamp' },
 * });
 * ```
 *
 * @template TFrameData - 帧数据类型
 * @template TInterpolations - 返回的 interpolations 类型
 * @param params - 参数对象
 * @param params.animatedValue - Animated.Value 对象
 * @param params.frameData - 帧数据对象，key 为属性名，value 为各帧的值数组
 * @param params.frameCount - 总帧数
 * @param params.config - 可选的 interpolate 配置（如 extrapolate）
 * @returns interpolations 对象
 */
export function createInterpolations<
  TFrameData extends Record<string, number[]>,
  TInterpolations = Record<
    keyof TFrameData,
    Animated.AnimatedInterpolation<number>
  >,
>(params: {
  animatedValue: Animated.Value;
  frameData: TFrameData;
  frameCount: number;
  config?: Animated.InterpolationConfigType;
}): TInterpolations {
  const { animatedValue, frameData, frameCount, config } = params;
  const result: any = {};
  const inputRange = Array.from({ length: frameCount }, (_, i) => i);

  Object.keys(frameData).forEach(key => {
    result[key] = animatedValue.interpolate({
      inputRange,
      outputRange: frameData[key],
      ...config,
    });
  });

  return result;
}
